---
layout: ../../layouts/PageLayout.astro
title: useForm
description: API reference for the useForm composition API function
menuTitle: useForm()
order: 6
---

import DocTip from '@/components/DocTip.vue';
import CodeTitle from '@/components/CodeTitle.vue';
import DocBadge from '@/components/DocBadge.vue';

# useForm

`useForm` is a custom composition API function that allows you to group fields created by `useField` and aggregates their state. It should be used to create logical forms or custom form components similar to the `<Form/>` component which is just a consumer of `useForm`.

## Field Types

The `useForm` function has field typing capabilities if you need it, getting type information for your fields and their values can be very powerful when building complex forms.

By unlocking the field type you automatically get more strict information for the various properties/methods exposed by `useForm` like `setErrors` and `setTouched`. There are two ways you can get the advanced typing information for your fields, the first is to provide a generic type to `useForm`.

```ts
import { useForm } from 'vee-validate';

interface LoginForm {
  email: string;
  password: string;
}

// in your setup
const { errors } = useForm<LoginForm>();
```

Or simply provide initial values to `useForm` and it will automatically pick up the type of `initialValues` and use it for the field types.

```ts
import { useForm } from 'vee-validate';

const { errors, setErrors, setFieldValue } = useForm({
  initialValues: {
    email: '',
    password: '',
  },
});
```

Alternatively, you can use a [typed schema](/guide/composition-api/typed-schema/) to infer the form types from the validation schema if you are using yup or zod.

Whichever approach you prefer, you get full type information for your fields for all the functions exposed by `useForm`, here are a few examples.

```ts
import { useForm } from 'vee-validate';

interface LoginForm {
  email: string;
  password: string;
}

// in your setup
const { errors, setErrors, setFieldValue } = useForm<LoginForm>();

errors.value; // typed as { email?: string; password?: string }

setErrors({
  email: 'This field is invalid', // auto-complete for `email` and `password`
});

setFieldValue('email', 'example@gmail.com'); // auto-complete for the field name and its value type
```

For example if you were to do this in the previous example:

```ts
setFieldValue('age', 5); // ⛔️ TypeScript error
setFieldValue('email', 5); // ⛔️ TypeScript error
```

It will error out because `age` is not defined in the `LoginForm` type you defined. The second line errors out because the `email` field is typed as a `string`.

## API Reference

### Arguments

<CodeTitle level="4">

`validationSchema?: any`

</CodeTitle>

Enables form-level validation, uses the specified schema to validate the fields. The schema can be either valid vee-validate global validators or functions or a yup object schema.

<CodeTitle level="4">

`initialValues?: MaybeRef<Record<string, any>>`

</CodeTitle>

The initial values for the form, can be a reactive object or reference.

```js
const { ... } = useForm({
  initialValues: {
    email: 'example@gmail.com',
    password: 'p@$$w0rd',
  }
});
```

<CodeTitle level="4">

`initialErrors?: Record<string, string>`

</CodeTitle>

The initial errors for the fields, useful for non hydrated SSR applications like Laravel, errors are applied on mounted.

```js
const { ... } = useForm({
  initialErrors: {
    email: 'This email is invalid',
    password: 'Password too short',
  }
});
```

<CodeTitle level="4">

`initialTouched?: Record<string, any>`

</CodeTitle>

The initial touched status for the form fields, applied on mounted.

```js
const { ... } = useForm({
  initialTouched: {
    email: true, // touched
    password: false, // non-touched
  }
});
```

<CodeTitle level="4">

`validateOnMount?: boolean`

</CodeTitle>

If true, it will trigger validation for all fields once the form component is mounted.

### Composable API

The following sections documents each available property on the `useForm` composable.

<CodeTitle level="4">

`errors: Ref<Record<string, string>>`

</CodeTitle>

An object that maps field names to their error messages, it only takes the first error message of each field if multiple exists.

```js
const { errors } = useForm();

errors.value; // access the errors value
```

<CodeTitle level="4">

`errorBag: Ref<Record<string, string>>`

</CodeTitle>

An object that maps field names to all of their error messages.

```js
const { errorBag } = useForm();

errorBag.value.email; // email field errors
```

Here is an example of its shape:

```js
{
  email: ["this field is required", "this field must be a valid email"],
  password: "too short"
}
```

Any fields without error messages will not be included in the object. So you can safely iterate over it with `Object.keys()` knowing all the included fields are invalid.

<CodeTitle level="4">

`isSubmitting: Ref<boolean>`

</CodeTitle>

Indicates if the submission handler is still running, once it resolves/rejects it will be automatically set to false again.

```js
const { isSubmitting } = useForm();

isSubmitting.value; // true or false
```

<CodeTitle level="4">

`isValidating: Ref<boolean>`

</CodeTitle>

Indicates if the validate function is still running, once validate function is done it will be automatically set to `false` again.

```js
const { isValidating } = useForm();

isValidating.value; // true or false
```

<CodeTitle level="4">

`meta: ComputedRef<FormMeta>`

</CodeTitle>

A computed property that contains an aggregated meta information/flags reflecting the state of all the fields inside the form.

```ts
interface FormMeta {
  touched: boolean; // if at least one field is touched (was blurred)
  dirty: boolean; // if at least one field is dirty (manipulated)
  valid: boolean; // if the form doesn't have any error messages
  pending: boolean; // if at least one field is pending validation
  initialValues?: Record<string, any>; // a map of the form's initial values
}
```

**usage**

```js
const { meta } = useForm();

meta.value; // { valid: false, invalid: true, dirty: true, .... }
```

<CodeTitle level="4">

`values: Record<string, any>`

</CodeTitle>

A reactive property that contains the current form values, you should not try to mutate it directly.

```js
const { values } = useForm();

values; // { email: 'something@gmail.com', .... }
```

<CodeTitle level="4">

`setFieldError: (field: string, message: string | undefined) => void`

</CodeTitle>

Sets a field's error message, useful for setting messages form an API or that are not available as a validation rule. Setting the message to `undefined` or an empty string clears the errors and marks the field as valid.

```js
const { setFieldError } = useForm();

setFieldError('email', 'this email is already taken');

// Mark field as valid
setFieldError('email', undefined);
```

If you try to set an error for a field that doesn't exist, it will be added to the form's errors object and it will change the form's `valid` state

<CodeTitle level="4">

`setErrors: (fields: Record<string, string | undefined>) => void`

</CodeTitle>

Sets multiple fields error messages, uses `setFieldError` internally.

```js
const { setErrors } = useForm();

setErrors({
  email: 'this email is already taken',
  password: 'someone already has this password 🤪',
  firstName: undefined, // clears errors and marks the field as valid
});
```

<DocTip>

Any missing fields you didn't pass to `setErrors` will be unaffected and their state will not change

</DocTip>

<CodeTitle level="4">

`setFieldValue: (field: string, value: any) => void`

</CodeTitle>

Sets a field's value, if a field does not exist it will not be reflected in the `values` ref. This will trigger validation on the field whose value changed.

```js
const { setFieldValue } = useForm();

setFieldValue('email', 'example@gmail.com');
```

If you try to set a value for a field that doesn't exist, it will be added to the form's values object and will stay there until the next `resetForm` is called.

<CodeTitle level="4">

`setValues: (fields: Record<string, any>) => void`

</CodeTitle>

Sets all fields values, will trigger validation for the changed fields.

```js
const { setValues } = useForm();

setValues({
  email: 'example@gmail.com',
  password: 'p@a$$W0rD',
});
```

<CodeTitle level="4">

`setFieldTouched: (field: string, isTouched: boolean) => void`

</CodeTitle>

Sets a field's `touched` meta flag, if you set it for a non-existing field it will have no effect.

```js
const { setFieldTouched } = useForm();

setFieldTouched('email', true);
```

<CodeTitle level="4">

`setTouched: (fields: Record<string, boolean>) => void`

</CodeTitle>

Sets multiple fields `touched` meta flag, does not validate.

```js
const { setTouched } = useForm();

setTouched({
  email: true,
  password: false,
});
```

<CodeTitle level="4">

`validate: () => Promise<{ valid: boolean; errors: Record<string, string>}>`

</CodeTitle>

Validates all the fields and populates the `errors` object, returns a promise that resolves to an object containing aggregated validation result of all fields.

```js
const { validate } = useForm();

const { valid, errors } = await validate();
```

<CodeTitle level="4">

`validateField: (field: string) => Promise<{ valid: boolean; errors: string[] }>`

</CodeTitle>

Validates a specific field inside the form, returns a promise that resolves to an object containing the validation result.

```js
const { validateField } = useForm();

const { valid, errors } = await validateField('email');
```

<CodeTitle level="4">

`handleSubmit: (cb: SubmissionHandler) => (evt?: Event) => Promise<void>`

</CodeTitle>

This is a higher order function used to create `submit` event handlers, You shouldn't use it as a handler for the events directly but rather use it to create those handlers.

The handlers created using this function will automatically prevent form submission and stop the propagation of the submit event.

It accepts a function which runs after validating the form and if all fields are valid. The callback you pass will receive the form values as the first argument, which is an object containing the fields' values.

```vue
<template>
  <form @submit="onSubmit"></form>
</template>

<script setup>
import { useForm } from 'vee-validate';

const { handleSubmit } = useForm();

// use `onSubmit` as an event handler for your forms
const onSubmit = handleSubmit(values => {
  // pretty print the values object
  alert(JSON.stringify(values, null, 2));
});
</script>
```

For advanced forms, you may need to trigger various actions on the form in the `submit` handler. Your callback receives a `FormActions` object as part of the second argument along with the event object that triggered the submission if available.

```js
const { handleSubmit } = useForm();

const onSubmit = handleSubmit((values, actions) => {
  // Send data to API
  alert(JSON.stringify(values, null, 2));

  // the form object contains useful methods
  // set a single field value
  actions.setFieldValue('field', 'hello');
  // set multiple fields values
  actions.setValues({ email: 'value', password: 'hi' });
  // set a single field error
  actions.setFieldError('field', 'this field is bad');
  // set multiple fields errors
  actions.setErrors({ email: 'bad email', password: 'bad password' });
  // reset the form
  actions.resetForm();
});
```

`handleSubmit` contains a `withControlled` function that you can use to only submit fields controlled by `useField` or `useFieldModel`. Read the [guide](/guide/composition-api/handling-forms) for more information.

```vue
<template>
  <form @submit="onSubmit"></form>
</template>

<script setup>
import { useForm } from 'vee-validate';

const { handleSubmit } = useForm();

const onSubmit = handleSubmit.withControlled(values => {
  // Send only controlled values to the API
  // Only fields declared with `useField` or `useFieldModel` will be printed
  alert(JSON.stringify(values, null, 2));
});
</script>
```

<DocTip title="Virtual Forms">

You can use `handleSubmit` to submit **virtual forms** that may use `form` elements or not. As you may have noticed the snippet above doesn't really care if you are using forms or not.

</DocTip>

<CodeTitle level="4">

`submitForm: (evt: Event) => void`

</CodeTitle>

Unlike `handleSubmit` this function can be used as an event handler for form `submit` event, it will prevent the propagation and submission of the forms using it as long as they are invalid. Once all the fields are valid it will submit the form with the native HTML behavior following the `form` element's `action` and `method` attributes.

This is useful if you plan to handle form submissions using a backend API like Laravel or whatever.

```vue
<template>
  <form @submit="submitForm" action="/api/login" method="post">
    <!-- ... -->
  </form>
</template>

<script setup>
import { useForm } from 'vee-validate';

const { submitForm } = useForm();
</script>
```

<CodeTitle level="4">

`submitCount: number`

</CodeTitle>

The number of submission attempts by the user, it increments whenever `submitForm` or `handleSubmit` callback are called.

<CodeTitle level="4">

`resetForm: (state?: Partial<FormState>, opts?: ResetFormOpts) => void`

</CodeTitle>

Clears error messages, resets the meta state for all fields and reverts their values to their initial state as well as the `submitCount` state. Accepts an optional object containing the new form state, useful if you need to reset the form values to different values other than their initial state.

This is the `FormState` interface:

```ts
type TouchedFlags = { [k: string]: boolean };

interface FormState {
  // any error messages
  errors: Record<string, string>;
  // touched meta flags
  touched: TouchedFlags;
  // Form Values
  values: Record<string, any>;
  // The form submit attempts count
  submitCount: number;
}
```

In this example, the `resetForm` function is updating the fields current values to the ones provided, these values will be used as the new initial values for future `resetForm` or `handleReset` calls. This also applies if the `Field` component or `useField` used their individual `resetField` function.

```js
const { resetForm } = useForm();

// ...
function onSubmit(values) {
  // send values to the API
  // ...

  // Reset the form values
  resetForm({
    values: {
      firstName: '',
      lastName: '',
      email: '',
      password: '',
    },
  });
}
```

By default `resetForm` merges the previous initial values with the new one provided, meaning only the provided ones will be overwritten. You can overwrite all the fields by passing `force: true` in the second argument.

```js
const { values, resetForm } = useForm({
  initialValues: { fname: '123', lname: '456' },
});

// values: { fname: '123', lname: '456' }
resetForm({ values: { fname: 'test' } });

// values: { fname: 'test' }
resetForm({ values: { fname: 'test' } }, { force: true });
```

<CodeTitle level="4">

`handleReset: () => void`

</CodeTitle>

Clears error messages, resets the meta state for all fields and reverts their values to their initial state as well as the `submitCount` state. you can use this function as handler for the `reset` events on native form elements.

```vue
<template>
  <form @reset="handleReset">
    <!-- ... -->
  </form>
</template>

<script setup>
import { useForm } from 'vee-validate';

const { handleReset } = useForm();

// you can use it in your code
handleReset();
</script>
```

<CodeTitle level="4">

`useFieldModel`

</CodeTitle>

<DocTip>

This is deprecated, please use `defineField` instead.

</DocTip>

This creates a bindable two-way model value for the specified fields, there are a couple of signatures for `useFieldModel`. Must be called in the `setup` function.

`useFieldModel` accepts either a single field path or multiple via an array. You can use either root field paths or nested paths like `some.user.path` with dot notation.

```vue
<template>
  <input name="email" v-model="email" />
  <span>{{ errors.email }}</span>

  <input name="password" v-model="password" type="password" />
  <span>{{ errors.password }}</span>
</template>

<script setup>
import { useForm } from 'vee-validate';

const { errors, useFieldModel } = useForm();

const email = useFieldModel('email');
const password = useFieldModel('password');

// or multiple models at once
const [email, password] = useFieldModel(['email', 'password']);
</script>
```

<CodeTitle level="4">

`defineInputBinds`

</CodeTitle>

<DocTip>

This is deprecated, please use `defineField` instead.

</DocTip>

This creates a bindable object for the specified field. The bindable object only works with native HTML input elements, for components use `defineComponentBinds` instead.

The `defineInputBinds` must be called in the `setup` function.

`defineInputBinds` accepts a single field path, You can use either root field paths or nested paths like `some.user.path` with dot notation.

```vue
<template>
  <input v-bind="email" />
  <span>{{ errors.email }}</span>

  <input v-bind="password" type="password" />
  <span>{{ errors.password }}</span>
</template>

<script setup>
import { useForm } from 'vee-validate';

const { errors, defineInputBinds } = useForm();

const email = defineInputBinds('email');
const password = defineInputBinds('password');
</script>
```

<CodeTitle level="4">

`defineComponentBinds`

</CodeTitle>

<DocTip>

This is deprecated, please use `defineField` instead.

</DocTip>

This creates a bindable object for the specified field. The bindable object only works with components, for native HTML input elements use `defineInputBinds` instead.

The `defineComponentBinds` must be called in the `setup` function.

`defineComponentBinds` accepts a single field path, You can use either root field paths or nested paths like `some.user.path` with dot notation.

```vue
<template>
  <MyTextInput v-bind="email" />
  <span>{{ errors.email }}</span>

  <MyTextInput v-bind="password" type="password" />
  <span>{{ errors.password }}</span>
</template>

<script setup>
import { useForm } from 'vee-validate';
import MyTextInput from '@/components/MyTextInput.vue';

const { errors, defineComponentBinds } = useForm();

const email = defineComponentBinds('email');
const password = defineComponentBinds('password');
</script>
```

<CodeTitle level="4">

`defineField`

</CodeTitle>

This function returns a model and a props/attributes pair.

The `defineField` must be called in the `setup` function.

`defineField` accepts a single field path, You can use either root field paths or nested paths like `some.user.path` with dot notation.

```vue
<template>
  <input v-model="email" v-bind="emailProps" />
  <span>{{ errors.email }}</span>

  <input v-model="password" v-bind="passwordProps" type="password" />
  <span>{{ errors.password }}</span>
</template>

<script setup>
import { useForm } from 'vee-validate';

const { errors, defineField } = useForm();

const [email, emailProps] = defineField('email');
const [password, passwordProps] = defineField('password');
</script>
```

This function also works with custom components.

You can configure the props/attributes that are bound to the component by passing a second argument to `defineField`. You can use this configuration to adjust the `field` validation behavior and more with the individual elements you are using or the component library of your choice. Check the [UI library examples](/examples/ui-libraries) for live examples.

```ts
const [field, props] = defineField('field', {
  // A getter that computes and adds any additional props to the component
  // It receives the current field state as an argument
  props(state) {
    // This is just an example, by default this is an empty object
    return {
      'aria-invalid': state.errors.length > 0 ? 'true' : 'false',
    };
  },
  // A label for the field, only used with global validation rules
  label: 'a label',
  // Validates when `blur` event is emitted from the element/component
  validateOnBlur: true,
  // Validates when `change` event is emitted from the element/component
  validateOnChange: true,
  // Validates when `input` event is emitted from the element/component
  validateOnInput: false,
  // Validates when the returned model value changes
  validateOnModelUpdate: true,
});
```

You can also have a lazy configuration by passing a function that returns the configuration object. The only difference is `props` is now a plain object instead of a getter function.

This means you can change any of the configuration based on the field state:

```ts
const [field, props] = defineField('field', state => {
  return {
    // A getter that computes and adds any additional props to the component
    props: {
      // This is just an example, by default this is an empty object
      'aria-invalid': state.errors.length > 0 ? 'true' : 'false',
    },
    // Validates when `blur` event is emitted from the element/component
    validateOnBlur: true,
    // Validates when `change` event is emitted from the element/component
    validateOnChange: true,
    // Validates when `input` event is emitted from the element/component
    validateOnInput: false,
    // Validates when the returned model value changes
    validateOnModelUpdate: true,
  };
});
```
